package sm.test;

import java.io.InputStream;
import java.sql.Blob;
import java.util.List;

import org.apache.mina.core.buffer.IoBuffer;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import sm.codec.DBDictCodec;
import sm.codec.api.Codec;
import sm.dbdict.def.DBDict;
import sm.dbdict.def.Field;
import sm.dbdict.def.SqlFieldOptions;
import sm.dbdict.def.StructureArrayOptions;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

public class FullTableCheck {

	private static Logger logger = LoggerFactory
			.getLogger(FullTableCheck.class);

	private static DBDict blobToDBDict(Codec codec, Blob blob) throws Exception {
		int length = (int) blob.length();
		byte[] bytes = new byte[length];
		InputStream is = blob.getBinaryStream();
		is.read(bytes);
		is.close();

		IoBuffer buffer = IoBuffer.wrap(bytes);
		DBDict des = (DBDict) codec.decode(buffer);
		return des;
	}

	private static Field getFieldByNameAndLevel(String name, int level,
			List<Field> fields) {
		for (Field field : fields) {
			if (name.equals(field.getName()) && level == field.getLevel()) {
				return field;
			}
		}
		return null;
	}

	private static boolean compareTwoObjects(Object obj1, Object obj2) {
		if (obj1 == null) {
			if (obj2 != null) {
				return false;
			} else {
				return true;
			}
		} else {
			if (obj2 == null) {
				return false;
			} else {
				return obj1.equals(obj2);
			}
		}
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		try {
			Codec codec = new DBDictCodec();
			SessionFactory sessionFactory = new Configuration().configure()
					.buildSessionFactory();
			Session session = sessionFactory.openSession();

			SQLQuery queryBarcap = session
					.createSQLQuery("select NAME, DESCRIPTOR from DBDICTM1_BARCAP where name = 'dbdict'");
			SQLQuery query = session
					.createSQLQuery("select NAME, DESCRIPTOR from DBDICTM1 where NAME = 'dbdict'");
			Object[] resultBarcap = (Object[]) queryBarcap.uniqueResult();
			Object[] result = (Object[]) query.uniqueResult();

			DBDict cm3r = blobToDBDict(codec, (Blob) result[1]);
			DBDict cm3rBarcap = blobToDBDict(codec, (Blob) resultBarcap[1]);

			Gson gson = new GsonBuilder().setPrettyPrinting().create();
			logger.info("cm3r: " + gson.toJson(cm3r));
			logger.info("cm3rBarcap: " + gson.toJson(cm3rBarcap));

			StringBuilder oldFieldBuilder = new StringBuilder();
			StringBuilder newFieldBuilder = new StringBuilder();
			for (Field field : cm3rBarcap.getField()) {
				String name = field.getName();
				int level = field.getLevel();
				Field newField = getFieldByNameAndLevel(name, level,
						cm3r.getField());
				if (newField == null) {
					// logger.info("delete field: " + name);
				} else {
					String oldDB2FieldName = field.getDb2_field_name();
					Integer oldDB2Length = field.getDb2_length();
					String oldStructure = field.getStructure();
					StructureArrayOptions oldStructureArrayOptions = field
							.getStructure_array_options();
					SqlFieldOptions oldSqlFieldOptions = field
							.getSql_field_options();
					Integer oldType = field.getType();

					String newDB2FieldName = newField.getDb2_field_name();
					Integer newDB2Length = newField.getDb2_length();
					String newStructure = newField.getStructure();
					StructureArrayOptions newStructureArrayOptions = field
							.getStructure_array_options();
					SqlFieldOptions newSqlFieldOptions = newField
							.getSql_field_options();

					if (oldSqlFieldOptions.getSql_column_name() != null
							&& oldSqlFieldOptions.getSql_table_alias().equals(
									"m1")) {
						String oldFieldName = oldSqlFieldOptions
								.getSql_column_name();
						oldFieldBuilder.append("\"" + oldFieldName + "\",");
						String newFieldName = newSqlFieldOptions
								.getSql_column_name();
						newFieldBuilder.append("\"" + newFieldName + "\",");

						if (!oldFieldName.equals(newFieldName)) {
							System.out.println("field name change from "
									+ oldFieldName + " to " + newFieldName);
						}
					}

					Integer newType = newField.getType();

					if (!compareTwoObjects(oldType, newType)) {
						logger.info("type change: " + name);
					}

					if (!compareTwoObjects(oldDB2FieldName, newDB2FieldName)) {
						logger.info("db2 field name change: " + name);
					}

					if (!compareTwoObjects(oldDB2Length, newDB2Length)) {
						logger.info("db2 length change: " + name);
					}

					if (!compareTwoObjects(oldStructure, newStructure)) {
						logger.info("structure change: " + name);
					}

					if (!compareTwoObjects(oldStructureArrayOptions,
							newStructureArrayOptions)) {
						logger.info("structure array options change: " + name);
					}

					if (!compareTwoObjects(oldSqlFieldOptions,
							newSqlFieldOptions)) {
						logger.info("sql field options change: " + name);
					}

				}
			}

			logger.info(oldFieldBuilder.toString());
			logger.info(newFieldBuilder.toString());

			session.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
